/***************************************************************************
 *   Copyright (C) 2007, 2009, 2010 by Lasse Liehu                         *
 *   lliehu@kolumbus.fi                                                    *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "unreadcountwindow.h"

#include <QAction>
#include <QBitmap>
#include <QMouseEvent>
#include <QPixmap>
#include <QPainter>
#include <QSpinBox>
#include <QLabel>
#include <QDialog>
#include <QCloseEvent>
#include <QSettings>
#include <QLineEdit>
#include <QPushButton>
#include <QGridLayout>

#include "google_reader_notifier_qt.h"
#include "notifiersettings.h"

UnreadCountWindow::UnreadCountWindow(const QString& svgFile,
    google_reader_notifier_qt& ref, QWidget *parent) : QWidget(parent),
    mRenderer(svgFile), mResizeBox(0), mTextToFitEdit(0), mRef(ref)
{
    // Set min and max sizes
    setMinimumWidth(22);
    setMinimumHeight(22);
    setMaximumWidth(512);
    setMaximumHeight(512);

    // Set context menu
    QAction *resizeAct = new QAction(tr("Resize..."), this);
    connect(resizeAct, SIGNAL(triggered()), this,
        SLOT(slotShowResizeDialog()));
    addAction(resizeAct);
    QAction *closeAct = new QAction(tr("Close this window"), this);
    connect(closeAct, SIGNAL(triggered()), this, SLOT(slotClose()) );
    addAction(closeAct);
    setContextMenuPolicy(Qt::ActionsContextMenu);

    updateUnreadCount("");
    setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
    setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint |
                   Qt::Tool | Qt::X11BypassWindowManagerHint);

    // Read saved pos and size from settings
    slotReadPosAndSize();

    updateUnreadCount(QString::number(mRef.unreadCountCache().value("system/total", 0) ) );
    repaint(rect() );
}

UnreadCountWindow::~UnreadCountWindow()
{
}

QSize UnreadCountWindow::sizeHint()
{
    // FIXME code this properly!
    // I WONDER what that means?
    return QSize(22,22);
}

bool UnreadCountWindow::isSvgRendererValid()
{
    return mRenderer.isValid();
}

void UnreadCountWindow::updateUnreadCount(const QString& newCountStr)
{
    mUnreadCountStr = newCountStr;
    if (mUnreadCountStr.isEmpty() ) mUnreadCountStr = "0";
    QString toolTipMsg;
    if (mUnreadCountStr == "0")
    {
        toolTipMsg += tr("No unread items in Google Reader.\n\n");
    }
    else
    {
        toolTipMsg += tr("%n unread item(s) in Google Reader.\n\n", "",
                         mUnreadCountStr.toInt() );
    }
    toolTipMsg += tr("Quick help:\nDrag the window with left mouse button.\n"
        "The Right moue button opens a context menu.\nNote that left is "
        "right and right is left on\nleft-handed mice.");
    setToolTip(toolTipMsg);
    // TODO window title!
    repaint(rect() );
}

void UnreadCountWindow::closeEvent(QCloseEvent *evt)
{
    // NOTE size is saved in resizeEvent()
    // NOTE position is saved in moveEvent()
    evt->accept();
}

void UnreadCountWindow::mouseMoveEvent(QMouseEvent *evt)
{
    if (evt->buttons() & Qt::LeftButton)
    {
        move(evt->globalPos() - mDragPos);
        evt->accept();
    }
}

void UnreadCountWindow::mousePressEvent(QMouseEvent *evt)
{
    if (evt->button() == Qt::LeftButton)
    {
        mDragPos = evt->globalPos() - frameGeometry().topLeft();
        evt->accept();
    }
}

void UnreadCountWindow::paintEvent(QPaintEvent *evt)
{
    QPainter painter(this);
    mRenderer.render(&painter, rect());

    QFont font(mRef.settings().unreadCountDisplayFont() );
    font.setBold(true);
    google_reader_notifier_qt::fitTextIntoWidth(mUnreadCountStr,
        rect().size().width(), font);
    QFontMetrics fm(font);
    bool cannotDrawCount = false;
    if (fm.width(mUnreadCountStr) > rect().size().width() )
    {
        resize(fm.width(mUnreadCountStr), fm.width(mUnreadCountStr));
        font = QFont(mRef.settings().unreadCountDisplayFont() );
        font.setBold(true);
        google_reader_notifier_qt::fitTextIntoWidth(mUnreadCountStr,
            rect().size().width(), font);
        QFontMetrics fm2(font);
        if (fm2.width(mUnreadCountStr ) > rect().size().width() )
        {
            cannotDrawCount = true;
            font = QFont(mRef.settings().unreadCountDisplayFont() );
            font.setBold(true);
            google_reader_notifier_qt::fitTextIntoWidth("#",
                rect().size().width(), font);
        }
    }

    painter.setFont(font);
    if (mUnreadCountStr != "X") painter.setPen(Qt::black);
    else painter.setPen("crimson");
    if (cannotDrawCount)
    {
        painter.drawText(rect(), Qt::AlignHCenter | Qt::AlignVCenter, "#");
    }
    else
    {
        painter.drawText(rect(), Qt::AlignHCenter | Qt::AlignVCenter,
            mUnreadCountStr );
    }
}

void UnreadCountWindow::moveEvent(QMoveEvent *evt)
{
    QSettings settings("Lasse Liehu", "Google Reader Notifier Qt");
    settings.setValue("unreadcountwindow_pos", pos() );
}

void UnreadCountWindow::resizeEvent(QResizeEvent *evt)
{
    if (rect().size().width() != rect().size().height() )
    {
        int newSide = qMax(size().height(), size().width());
        resize(newSide, newSide);
        return;
    }
    QPixmap pm(rect().size().width(), rect().size().height());
    pm.fill(Qt::transparent);
    QPainter painter1(&pm);
    mRenderer.render(&painter1);
    setMask( pm.createMaskFromColor(Qt::transparent, Qt::MaskInColor) );

    if (mResizeBox)
    {
        mResizeBox->setValue(rect().size().width() );
    }

    QSettings settings("Lasse Liehu", "Google Reader Notifier Qt");
    settings.setValue("unreadcountwindow_size", size() );
}

void UnreadCountWindow::slotShowResizeDialog()
{
    if (mResizeBox) return;

    // Create widgets.
    QDialog *dialog = new QDialog(this);
    mResizeBox = new QSpinBox;
    mResizeBox->setMinimum(qMax(minimumWidth(), minimumHeight() ));
    mResizeBox->setMaximum(qMin(maximumWidth(), maximumHeight() ));
    mResizeBox->setValue(qMax(size().width(), size().height() ));
    QSizePolicy policy = mResizeBox->sizePolicy();
    policy.setHorizontalStretch(1);
    mResizeBox->setSizePolicy(policy);
    connect(mResizeBox, SIGNAL(valueChanged(int)), this, SLOT(slotResize(int)));
    QLabel *label = new QLabel(tr("&Width and height (in pixels):"));
    label->setBuddy(mResizeBox);
    mTextToFitEdit = new QLineEdit;
    QPushButton *resizeButton =
        new QPushButton(tr("Resize it so that given text fits in it"));

    // Set up the layout.
    QGridLayout *layout = new QGridLayout;
    layout->addWidget(label, 0, 0);
    layout->addWidget(mResizeBox, 0, 1);
    layout->addWidget(mTextToFitEdit, 1, 0);
    layout->addWidget(resizeButton, 1, 1);
    layout->setColumnStretch(0, 1);
    dialog->setLayout(layout);

    // Last initialisations & connections
    dialog->setWindowTitle(tr("Resize unread count window"));
    dialog->setAttribute(Qt::WA_DeleteOnClose);

    // Make signal & slot connections.
    connect(dialog, SIGNAL(destroyed()), this,
        SLOT(slotMarkResizeDialogDeleted()));
    connect(resizeButton, SIGNAL(clicked()), this,
        SLOT(slotResizeSoThatTheTextFitsIn() ));

    // Show it.
    dialog->exec();
}

/**
 * @note This is only used by this window's resize window. There is no reason to use this member functio when resizing this
  *     window. If you don't use this function then you must take care of height and width being of the same length.
 */
void UnreadCountWindow::slotResize(int newSideSize)
{
    resize(newSideSize, newSideSize);
}

void UnreadCountWindow::slotMarkResizeDialogDeleted()
{
    mResizeBox = 0;
    mTextToFitEdit = 0;
}

void UnreadCountWindow::slotResizeSoThatTheTextFitsIn()
{
    if (!mTextToFitEdit) return;

    slotResizeSoThatTheTextFitsIn(mTextToFitEdit->text());
}

void UnreadCountWindow::slotResizeSoThatTheTextFitsIn(const QString& text)
{
    if (text.isEmpty() ) return;

    QFont font(mRef.settings().unreadCountDisplayFont() );
    font.setBold(true);
    google_reader_notifier_qt::fitTextIntoWidth(text, rect().size().width(),
        font);
    QFontMetrics fm(font);
    int newWidth = fm.width(text);
    resize(newWidth, newWidth);
}

void UnreadCountWindow::slotReadPosAndSize()
{
    QSettings settings("Lasse Liehu", "Google Reader Notifier Qt");
    QPoint pos = settings.value("unreadcountwindow_pos", QPoint(0,0)).
        toPoint();
    QSize size = settings.value("unreadcountwindow_size",
        QSize(0, 0)).toSize();
    move(pos);
    if (size.isEmpty() )
    {
        slotResizeSoThatTheTextFitsIn("999");
    }
    else resize(size);
}

void UnreadCountWindow::slotClose()
{
    mRef.showUnreadCountWindowCloseMsg();
    close();
}
